package util

import (
	"ckeadm/constants"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

func init() {
	rand.Seed(time.Now().Unix())
}

func BackupFiles(files ...string) error {
	if len(files) == 0 {
		return nil
	}

	var backup = fmt.Sprintf("%s.%d.%s~", files[0], rand.Intn(10000), time.Now().Format("2006-01-02@15:04:05"))
	if err := os.Rename(files[0], backup); err != nil {
		return err
	}

	return BackupFiles(files[1:]...)
}

func WriteFile(file string, context string) error {
	err := os.MkdirAll(path.Dir(file), os.ModePerm)

	writer, err := os.OpenFile(filepath.Clean(file), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = fmt.Fprintln(writer, context)
	return err
}

func AppendFile(file string, context string) error {
	err := os.MkdirAll(path.Dir(file), os.ModePerm)

	writer, err := os.OpenFile(filepath.Clean(file), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return err
	}
	defer writer.Close()

	_, err = fmt.Fprintln(writer, context)
	return err
}

func DeleteMatchFiles(dirname, match string) error {
	if len(dirname) == 0 {
		dirname = "."
	}
	if len(dirname) != 0 && dirname[len(dirname)-1] != '/' {
		dirname += "/"
	}

	files, err := ioutil.ReadDir(dirname)
	if err != nil {
		return fmt.Errorf("while read dir, error: %s", err)
	}

	for _, file := range files {
		if regexp.MustCompile(match).MatchString(file.Name()) {
			_ = os.Remove(dirname + file.Name())
		}
	}

	return nil
}

func ListAllFilesInPath(filedir string) (files []string, err error) {
	err = filepath.Walk(filedir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			files = append(files, path)
		}
		return nil
	})

	if err == nil && len(files) == 0 {
		err = fmt.Errorf("no files find in path %s", filedir)
	}
	return
}

type DebugPrint bool

var Debug = DebugPrint(constants.Debug)

func (d *DebugPrint) Println(a ...interface{}) (n int, err error) {
	if *d == true {
		fmt.Println(a...)
	}
	return 0, nil
}

func (d *DebugPrint) Printf(format string, a ...interface{}) (n int, err error) {
	if *d == true {
		return fmt.Printf(format, a...)
	}
	return 0, nil
}

func ListSubDirsInPath(path string) ([]string, error) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, err
	}
	var dirs []string
	for _, file := range files {
		if file.IsDir() {
			dirs = append(dirs, file.Name())
		}
	}
	return dirs, nil
}

func GetLatestFileInPath(filedir string) (string, error) {
	var curFile string
	curModTime := time.Time{}
	err := filepath.Walk(filedir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			if info.ModTime().After(curModTime) {
				curFile = path
				curModTime = info.ModTime()
			}
		}
		return nil
	})

	if err != nil {
		return "", err
	}
	return curFile, nil
}

func GetLatestFileInPathWithName(filedir, name string) (string, error) {
	var curFile string
	curModTime := time.Time{}
	err := filepath.Walk(filedir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			if (strings.Contains(path, name)) && (info.ModTime().After(curModTime)) {
				curFile = path
				curModTime = info.ModTime()
			}
		}
		return nil
	})

	if err != nil {
		return "", err
	}
	return curFile, nil
}

// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
	_, err := os.Stat(path) //os.Stat获取文件信息
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}
	return true
}
